package com.matrix.auth.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.teaopenapi.models.Config;
import com.matrix.auth.config.AliyunSmsProperties;
import com.matrix.auth.service.SmsService;
import com.matrix.common.constant.RedisConstants;
import com.matrix.common.enums.SmsTypeEnum;
import com.matrix.common.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @author 有点甜
 * @since 2025/7/25
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class SmsServiceImpl implements SmsService {

    private final StringRedisTemplate redisTemplate;
    private final AliyunSmsProperties smsProperties;

    @Override
    public void sendCode(String phone, SmsTypeEnum type) {
        String limitKey = RedisConstants.buildKey(RedisConstants.SMS_LIMIT_KEY, type.getCode(), phone);
        if (redisTemplate.hasKey(limitKey)) {
            throw new BusinessException("短信发送过于频繁,请稍后再试");
        }

        String code = RandomUtil.randomNumbers(6);

        try {
            Config config = new Config()
                    .setAccessKeyId(smsProperties.getAccessKeyId())
                    .setAccessKeySecret(smsProperties.getAccessKeySecret());
            config.endpoint = smsProperties.getEndpoint();
            Client client = new Client(config);

            SendSmsRequest sendSmsRequest = new SendSmsRequest()
                    .setSignName(smsProperties.getSignName())
                    .setTemplateCode(smsProperties.getTemplateCode())
                    .setPhoneNumbers(phone)
                    .setTemplateParam("{\"code\":\"" + code + "\"}");

            log.info("向手机 {} 发送类型为 {} 的验证码: {}", phone, type.getDescription(), code);
            // client.sendSms(sendSmsRequest);

        } catch (Exception e) {
            log.error("阿里云短信发送失败", e);
            throw new BusinessException("验证码发送失败,请联系管理员");
        }

        String codeKey = RedisConstants.buildKey(RedisConstants.SMS_CODE_KEY, type.getCode(), phone);
        String retryKey = RedisConstants.buildKey(RedisConstants.SMS_RETRY_KEY, type.getCode(), phone);
        redisTemplate.opsForValue().set(limitKey, "1", 1, TimeUnit.MINUTES);
        redisTemplate.opsForValue().set(codeKey, code, 5, TimeUnit.MINUTES);
        redisTemplate.opsForValue().set(retryKey, "0", 5, TimeUnit.MINUTES);
    }

    @Override
    public void verifyCode(String phone, SmsTypeEnum type, String inputCode) {
        String limitKey = RedisConstants.buildKey(RedisConstants.SMS_LIMIT_KEY, type.getCode(), phone);
        String codeKey = RedisConstants.buildKey(RedisConstants.SMS_CODE_KEY, type.getCode(), phone);
        String retryKey = RedisConstants.buildKey(RedisConstants.SMS_RETRY_KEY, type.getCode(), phone);

        String storedCode = redisTemplate.opsForValue().get(codeKey);

        if (storedCode == null) {
            throw new BusinessException("验证码已过期或不存在,请重新发送");
        }

        Long retryCount = redisTemplate.opsForValue().increment(retryKey);
        if (retryCount != null && retryCount > 3) {
            redisTemplate.delete(codeKey);
            redisTemplate.delete(retryKey);
            throw new BusinessException("验证码输入错误次数过多,已作废");
        }

        if (!storedCode.equals(inputCode)) {
            throw new BusinessException("验证码错误");
        }

        redisTemplate.delete(limitKey);
        redisTemplate.delete(codeKey);
        redisTemplate.delete(retryKey);
    }
}
